/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package neuralmusic.midiIO;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;

import neuralmusic.brain.module.Excitable;
import neuralmusic.brain.module.Scheduler;
import neuralmusic.brain.module.Location;
import neuralmusic.brain.module.Point;



/**
 *
 * @author pjl
 */
public class NoteAction implements Location,Excitable  {
    private final int pitch;
    private final Receiver recv;
    private final ShortMessage mess;
    int chn=0;
    int cmd=ShortMessage.NOTE_ON;
    private int vel;
    static boolean playing=false;
    double onThresh=.4;
    double offThresh=.1;
    Point pt;
    double oldStamp;
    double state;
    double tConst=1;
    double gain=.8;
	private double lastUpdateTime;
	private Scheduler fireQueue;
    
    public NoteAction(Receiver recv,int pitch,int chn,Scheduler fireQueue) {
    	assert(fireQueue != null);
        this.recv=recv;
        this.pitch=pitch;
        this.chn=chn;
        mess=new ShortMessage();
        this.fireQueue=fireQueue;
        //this.pt=pt;
    }

    @Override
	public
    void excite(float valIn) {
    	
    	//System.out.println(" Note excite" + pitch+ " : " + valIn);
    	updateState();
    	
    	 	
    	
      	if (playing) {
    		if (state < offThresh) {
    			state=0;
    			playing=false;
    		} else {
    			return;
    		}
      	}  	
    	
    	
    	this.state += valIn*gain;
    //	System.out.println(this.state);
    	
    	if (!playing) {
    		if (state > onThresh) {
    			playing=true;
    		} else {
    			return;
    		}
    	}
    	
    	vel=Math.min((int) (state * 127),127);
    //	System.out.println(" Whohey" +vel);
        try {
            mess.setMessage(cmd, chn, pitch, 0);
            recv.send(mess, -1);
            mess.setMessage(cmd, chn, pitch, vel);
           // System.out.println("pit,vel=" + pitch + "  " + vel);
            recv.send(mess, -1);
        } catch (InvalidMidiDataException ex) {
            Logger.getLogger(NoteAction.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    int  getMidiValue() {
        return vel;
    }
    

    public void setPoint(Point pt) {
    	this.pt=pt;
    }
    @Override
    public Point getPoint() {
        return pt;
    }

    @Override
    public float getDisplayValue() {
    	updateState();
         return (float) state;
    }
    
    // apply any pending decay due to time lasped to the state.
    public void updateState() {
        double now = fireQueue.getCurrentTimeInSecs();
        state = state * Math.exp(-tConst * (now - lastUpdateTime));
        lastUpdateTime = now;
    }

//	@Override
//	public Object getId() {
//		// TODO Auto-generated method stub
//		return null;
//	}


}
